/*
 * MainWindow.java
 *
 * Created on 2009-12-27, 00:22:54
 */

package gui;

import de.uniba.wiai.lspi.chord.service.ServiceException;
import gui.observer.ServerObserver;
import java.awt.Component;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.util.Vector;
import javax.swing.JOptionPane;
import net.*;
import routing.OpenChordWrapper;
import routing.UserData;
import routing.exception.BadPortException;
import routing.exception.BadSignatureException;
import routing.exception.UserExistException;
import routing.exception.UserNotFoundException;
import user.Contacts;

/**
 *
 * @author Paweł Kopiczko
 */
public class MainWindow extends javax.swing.JFrame {
    private OpenChordWrapper openChordWrapper = new OpenChordWrapper();
    private Contacts contacts;
    private int jTabbedPaneLastIndex = 0;
    private String username;

    /** Creates new form MainWindow */
    public MainWindow() {
//        javax.swing.UIManager.LookAndFeelInfo[] lfi = UIManager.getInstalledLookAndFeels();
//        try {
//            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
//        } catch (ClassNotFoundException ex) {
//            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
//        } catch (InstantiationException ex) {
//            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
//        } catch (IllegalAccessException ex) {
//            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
//        } catch (UnsupportedLookAndFeelException ex) {
//            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
//        }
        initComponents();
        initContactList();
        initServer();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jFrame1 = new javax.swing.JFrame();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPopupMenuContactList = new javax.swing.JPopupMenu();
        jMenuItemContactListTalk = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        jMenuItemContactListAddNew = new javax.swing.JMenuItem();
        jMenuItemContactListRemove = new javax.swing.JMenuItem();
        jDialogConnect = new javax.swing.JDialog();
        jLabel2 = new javax.swing.JLabel();
        jButton3 = new javax.swing.JButton();
        jTextField2 = new javax.swing.JTextField();
        jTextField3 = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        jDialogSettings = new javax.swing.JDialog();
        jFormattedTextField2 = new javax.swing.JFormattedTextField();
        jLabel3 = new javax.swing.JLabel();
        jButton4 = new javax.swing.JButton();
        jDialogRegistration = new javax.swing.JDialog();
        jButton5 = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        jLabel4 = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jPasswordField1 = new javax.swing.JPasswordField();
        jLabel6 = new javax.swing.JLabel();
        jPasswordField2 = new javax.swing.JPasswordField();
        jFrameSearch = new javax.swing.JFrame();
        jTextField4 = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        jButton6 = new javax.swing.JButton();
        jDialogLogIn = new javax.swing.JDialog();
        jTextField5 = new javax.swing.JTextField();
        jPasswordField3 = new javax.swing.JPasswordField();
        jLabel9 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        jButton7 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jButton1 = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenuChord = new javax.swing.JMenu();
        jMenuConnect = new javax.swing.JMenu();
        jMenuItemConnectToExisiting = new javax.swing.JMenuItem();
        jMenuItemConncectCreateNew = new javax.swing.JMenuItem();
        jMenuItemDisconnect = new javax.swing.JMenuItem();
        jMenuUser = new javax.swing.JMenu();
        jMenuItemRegister = new javax.swing.JMenuItem();
        jMenuItemLogIn = new javax.swing.JMenuItem();
        jMenuItemLogOut = new javax.swing.JMenuItem();
        jMenuItemRemove = new javax.swing.JMenuItem();

        jFrame1.setTitle("Conversation with...");
        jFrame1.setMinimumSize(new java.awt.Dimension(460, 364));

        jTabbedPane1.setDoubleBuffered(true);
        jTabbedPane1.setPreferredSize(new java.awt.Dimension(460, 344));
        jTabbedPane1.addContainerListener(new java.awt.event.ContainerAdapter() {
            public void componentRemoved(java.awt.event.ContainerEvent evt) {
                jTabbedPane1ComponentRemoved(evt);
            }
        });

        javax.swing.GroupLayout jFrame1Layout = new javax.swing.GroupLayout(jFrame1.getContentPane());
        jFrame1.getContentPane().setLayout(jFrame1Layout);
        jFrame1Layout.setHorizontalGroup(
            jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 460, Short.MAX_VALUE)
        );
        jFrame1Layout.setVerticalGroup(
            jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE)
        );

        jMenuItemContactListTalk.setText("talk");
        jMenuItemContactListTalk.setEnabled(false);
        jMenuItemContactListTalk.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemContactListTalkActionPerformed(evt);
            }
        });
        jPopupMenuContactList.add(jMenuItemContactListTalk);
        jPopupMenuContactList.add(jSeparator1);

        jMenuItemContactListAddNew.setText("add new...");
        jMenuItemContactListAddNew.setEnabled(false);
        jMenuItemContactListAddNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemContactListAddNewActionPerformed(evt);
            }
        });
        jPopupMenuContactList.add(jMenuItemContactListAddNew);

        jMenuItemContactListRemove.setText("remove");
        jMenuItemContactListRemove.setEnabled(false);
        jMenuItemContactListRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemContactListRemoveActionPerformed(evt);
            }
        });
        jPopupMenuContactList.add(jMenuItemContactListRemove);

        jDialogConnect.setTitle("Connection to overlay network...");
        jDialogConnect.setMinimumSize(new java.awt.Dimension(427, 137));
        jDialogConnect.setResizable(false);
        jDialogConnect.setLocationRelativeTo(null);

        jLabel2.setText("IP address of bootstrap node:");

        jButton3.setText("OK");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jTextField3.setText("5959");
        jTextField3.setEnabled(false);
        jTextField3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextField3ActionPerformed(evt);
            }
        });

        jLabel7.setText("Listening port number of bootsrrap node:");
        jLabel7.setEnabled(false);

        javax.swing.GroupLayout jDialogConnectLayout = new javax.swing.GroupLayout(jDialogConnect.getContentPane());
        jDialogConnect.getContentPane().setLayout(jDialogConnectLayout);
        jDialogConnectLayout.setHorizontalGroup(
            jDialogConnectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogConnectLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jDialogConnectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jDialogConnectLayout.createSequentialGroup()
                        .addGroup(jDialogConnectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel2)
                            .addComponent(jLabel7))
                        .addGap(50, 50, 50)
                        .addGroup(jDialogConnectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 145, Short.MAX_VALUE))
                        .addContainerGap())
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jDialogConnectLayout.createSequentialGroup()
                        .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(159, 159, 159))))
        );
        jDialogConnectLayout.setVerticalGroup(
            jDialogConnectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogConnectLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jDialogConnectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jDialogConnectLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel7)
                    .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jButton3)
                .addContainerGap(32, Short.MAX_VALUE))
        );

        jDialogSettings.setTitle("Settings");
        jDialogSettings.setIconImage(null);
        jDialogSettings.setMinimumSize(new java.awt.Dimension(353, 103));
        jDialogSettings.setModal(true);
        jDialogSettings.setResizable(false);
        jDialogSettings.setLocationRelativeTo(null);

        jFormattedTextField2.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("###"))));

        jLabel3.setText("Listening port number for p2p network:");

        jButton4.setText("OK");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jDialogSettingsLayout = new javax.swing.GroupLayout(jDialogSettings.getContentPane());
        jDialogSettings.getContentPane().setLayout(jDialogSettingsLayout);
        jDialogSettingsLayout.setHorizontalGroup(
            jDialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogSettingsLayout.createSequentialGroup()
                .addGroup(jDialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jDialogSettingsLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jLabel3)
                        .addGap(18, 18, 18)
                        .addComponent(jFormattedTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(jDialogSettingsLayout.createSequentialGroup()
                        .addGap(111, 111, 111)
                        .addComponent(jButton4, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jDialogSettingsLayout.setVerticalGroup(
            jDialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogSettingsLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jDialogSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(jFormattedTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(jButton4)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jDialogRegistration.setTitle("Registration");
        jDialogRegistration.setMinimumSize(new java.awt.Dimension(250, 150));
        jDialogRegistration.setResizable(false);

        jButton5.setText("Register");
        jButton5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton5ActionPerformed(evt);
            }
        });

        jPanel1.setLayout(new java.awt.GridLayout(3, 2));

        jLabel4.setText("Username:");
        jPanel1.add(jLabel4);
        jPanel1.add(jTextField1);

        jLabel5.setText("Password:");
        jPanel1.add(jLabel5);
        jPanel1.add(jPasswordField1);

        jLabel6.setText("Retype password:");
        jPanel1.add(jLabel6);
        jPanel1.add(jPasswordField2);

        javax.swing.GroupLayout jDialogRegistrationLayout = new javax.swing.GroupLayout(jDialogRegistration.getContentPane());
        jDialogRegistration.getContentPane().setLayout(jDialogRegistrationLayout);
        jDialogRegistrationLayout.setHorizontalGroup(
            jDialogRegistrationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogRegistrationLayout.createSequentialGroup()
                .addGroup(jDialogRegistrationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jDialogRegistrationLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE))
                    .addGroup(jDialogRegistrationLayout.createSequentialGroup()
                        .addGap(132, 132, 132)
                        .addComponent(jButton5)))
                .addContainerGap())
        );
        jDialogRegistrationLayout.setVerticalGroup(
            jDialogRegistrationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogRegistrationLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jButton5)
                .addContainerGap())
        );

        jFrameSearch.setTitle("Adding new user");
        jFrameSearch.setMinimumSize(new java.awt.Dimension(312, 101));
        jFrameSearch.setResizable(false);
        jFrameSearch.setLocationRelativeTo(null);

        jLabel8.setText("Write username to add:");

        jButton6.setText("Add");
        jButton6.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton6ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jFrameSearchLayout = new javax.swing.GroupLayout(jFrameSearch.getContentPane());
        jFrameSearch.getContentPane().setLayout(jFrameSearchLayout);
        jFrameSearchLayout.setHorizontalGroup(
            jFrameSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jFrameSearchLayout.createSequentialGroup()
                .addGroup(jFrameSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jFrameSearchLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jLabel8)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jTextField4, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE))
                    .addGroup(jFrameSearchLayout.createSequentialGroup()
                        .addGap(114, 114, 114)
                        .addComponent(jButton6)))
                .addContainerGap())
        );
        jFrameSearchLayout.setVerticalGroup(
            jFrameSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jFrameSearchLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jFrameSearchLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextField4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel8))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton6)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jDialogLogIn.setMinimumSize(new java.awt.Dimension(250, 132));
        jDialogLogIn.setResizable(false);

        jLabel9.setText("Username:");

        jLabel10.setText("Password:");

        jButton7.setText("Log in");
        jButton7.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton7ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jDialogLogInLayout = new javax.swing.GroupLayout(jDialogLogIn.getContentPane());
        jDialogLogIn.getContentPane().setLayout(jDialogLogInLayout);
        jDialogLogInLayout.setHorizontalGroup(
            jDialogLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogLogInLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jDialogLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jButton7, javax.swing.GroupLayout.DEFAULT_SIZE, 188, Short.MAX_VALUE)
                    .addGroup(jDialogLogInLayout.createSequentialGroup()
                        .addGroup(jDialogLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel10)
                            .addComponent(jLabel9))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jDialogLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPasswordField3, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE)
                            .addComponent(jTextField5, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE))))
                .addContainerGap())
        );
        jDialogLogInLayout.setVerticalGroup(
            jDialogLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jDialogLogInLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jDialogLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextField5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel9))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jDialogLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel10)
                    .addComponent(jPasswordField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton7)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Communicator");
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setMinimumSize(new java.awt.Dimension(180, 180));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jList1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jList1.setComponentPopupMenu(jPopupMenuContactList);
        jScrollPane1.setViewportView(jList1);

        jButton1.setText("Talk");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jMenuChord.setText("Chord");

        jMenuConnect.setText("Connect");

        jMenuItemConnectToExisiting.setText("To existing newtork...");
        jMenuItemConnectToExisiting.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemConnectToExisitingActionPerformed(evt);
            }
        });
        jMenuConnect.add(jMenuItemConnectToExisiting);

        jMenuItemConncectCreateNew.setText("Create new network");
        jMenuItemConncectCreateNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemConncectCreateNewActionPerformed(evt);
            }
        });
        jMenuConnect.add(jMenuItemConncectCreateNew);

        jMenuChord.add(jMenuConnect);

        jMenuItemDisconnect.setText("Disconnect");
        jMenuItemDisconnect.setEnabled(false);
        jMenuItemDisconnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDisconnectActionPerformed(evt);
            }
        });
        jMenuChord.add(jMenuItemDisconnect);

        jMenuBar1.add(jMenuChord);

        jMenuUser.setText("User");
        jMenuUser.setEnabled(false);

        jMenuItemRegister.setText("Register");
        jMenuItemRegister.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemRegisterActionPerformed(evt);
            }
        });
        jMenuUser.add(jMenuItemRegister);

        jMenuItemLogIn.setText("Log in");
        jMenuItemLogIn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemLogInActionPerformed(evt);
            }
        });
        jMenuUser.add(jMenuItemLogIn);

        jMenuItemLogOut.setText("Log out");
        jMenuItemLogOut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemLogOutActionPerformed(evt);
            }
        });
        jMenuUser.add(jMenuItemLogOut);

        jMenuItemRemove.setText("Remove");
        jMenuItemRemove.setEnabled(false);
        jMenuItemRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemRemoveActionPerformed(evt);
            }
        });
        jMenuUser.add(jMenuItemRemove);

        jMenuBar1.add(jMenuUser);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
            .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton1))
        );

        setBounds(0, 0, 284, 504);
    }// </editor-fold>//GEN-END:initComponents

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        initConversation((String) jList1.getSelectedValue());
    }//GEN-LAST:event_jButton1ActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        contacts.save();
        for(Component c : jTabbedPane1.getComponents()) {
            try {
                ((TalkPane) c).close();
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
//        try {
//            ChordTools.LeaveNetwork();
//        } catch (Exception ex) {
//            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
//        }
    }//GEN-LAST:event_formWindowClosing

    private void jTabbedPane1ComponentRemoved(java.awt.event.ContainerEvent evt) {//GEN-FIRST:event_jTabbedPane1ComponentRemoved
//        try {
//            //((TalkPane) evt.getComponent()).close();
//        } catch (IOException ex) {
//            JOptionPane.showMessageDialog(null, "Could not close connection: " + ex);
//        }
    }//GEN-LAST:event_jTabbedPane1ComponentRemoved

    private void jMenuItemContactListTalkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemContactListTalkActionPerformed
        initConversation((String) jList1.getSelectedValue());
    }//GEN-LAST:event_jMenuItemContactListTalkActionPerformed

    private void jMenuItemDisconnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDisconnectActionPerformed
//        try {
//            ChordTools.LeaveNetwork();
//            java.awt.EventQueue.invokeLater(new Runnable() {
//                public void run() {
//                    jMenuConnect.setEnabled(true);
//                    jMenuItemDisconnect.setEnabled(false);
//                    jMenuUser.setEnabled(false);
//                }
//            });
//        } catch (ServiceException ex) {
//            showMessage("Error when leaving p2p network!");
//        } catch (PasswordNotMatchedException ex) {
//            showMessage("Error when logging out: " + ex.getMessage());
//        }
    }//GEN-LAST:event_jMenuItemDisconnectActionPerformed

    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed
        String username = jTextField1.getText();
        if (!username.matches("[A-Za-z_0-9]{3,}")) {
            showMessage("Username must have more than 2 symbols\nand may only contain letters and digits");
            return;
        }
        String password = new String(jPasswordField1.getPassword());
        if (!password.equals(new String(jPasswordField2.getPassword()))) {
            showMessage("Passwords do not match!");
            return;
        }
        if (!password.matches("[\\S]{5,}")) {
            showMessage("Password must be 5 or more characters length and can not contain white spaces");
            return;
        }
        try {
            openChordWrapper.insertUser(username, password);
            jDialogRegistration.setVisible(false);
        } catch (UserExistException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (InvalidKeyException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (SignatureException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (NullPointerException ex) {
            JOptionPane.showMessageDialog(null, "No more users in the network!");
        }
    }//GEN-LAST:event_jButton5ActionPerformed

    private void jMenuItemRegisterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemRegisterActionPerformed
        jDialogRegistration.setVisible(true);
    }//GEN-LAST:event_jMenuItemRegisterActionPerformed

    private void jMenuItemConncectCreateNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemConncectCreateNewActionPerformed
        try {
            openChordWrapper = new OpenChordWrapper();
            openChordWrapper.create(NetSettings.UDP_PORT);
            jMenuConnect.setEnabled(false);
            jMenuItemDisconnect.setEnabled(true);
            jMenuUser.setEnabled(true);
        } catch (BadPortException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UnknownHostException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (MalformedURLException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
    }//GEN-LAST:event_jMenuItemConncectCreateNewActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        String bootstrapIP = jTextField2.getText();
        if (!bootstrapIP.matches("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")) {
            JOptionPane.showMessageDialog(null, "Invalid IP adress!");
            return;
        }
        int bootstrapPort = Integer.parseInt(jTextField3.getText());
        if (bootstrapPort > 65535 || bootstrapPort < 1024) {
            JOptionPane.showMessageDialog(null, "Inavlid port number");
            return;
        }
        openChordWrapper = new OpenChordWrapper();
        try {
            openChordWrapper.join(NetSettings.UDP_PORT, bootstrapIP, bootstrapPort);
            jMenuConnect.setEnabled(false);
            jMenuItemDisconnect.setEnabled(true);
            jMenuUser.setEnabled(true);
            jDialogConnect.setVisible(false);
        } catch (RuntimeException ex) {
            JOptionPane.showMessageDialog(null, "This should not happen. Try restart Your program.");
        } catch (UnknownHostException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, "Could not connect to the boostrtap node!");
            openChordWrapper = null;
            return;
        } catch (MalformedURLException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
    }//GEN-LAST:event_jButton3ActionPerformed

    private void jMenuItemConnectToExisitingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemConnectToExisitingActionPerformed
        jDialogConnect.setVisible(true);
    }//GEN-LAST:event_jMenuItemConnectToExisitingActionPerformed

    private void jMenuItemContactListAddNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemContactListAddNewActionPerformed
        jFrameSearch.setVisible(true);
    }//GEN-LAST:event_jMenuItemContactListAddNewActionPerformed

    private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton6ActionPerformed
        try {
            String username = jTextField4.getText();
            contacts.add(openChordWrapper.getUserData(username).getName());
            contacts.save();
            refreshContactList();
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UserNotFoundException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
    }//GEN-LAST:event_jButton6ActionPerformed

    private void jMenuItemLogInActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemLogInActionPerformed
        jDialogLogIn.setVisible(true);
    }//GEN-LAST:event_jMenuItemLogInActionPerformed

    private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton7ActionPerformed
        try {
            String username = jTextField5.getText();
            String password = new String(jPasswordField3.getPassword());
            if (!openChordWrapper.checkPassword(username, password)) {
                JOptionPane.showMessageDialog(null, "Incorrect login or password");
                return;
            }
            openChordWrapper.changeState(username, true);
            this.username = username;
            jMenuItemLogOut.setEnabled(true);
            jMenuItemLogIn.setEnabled(false);
            jMenuItemRegister.setEnabled(false);
            jMenuItemRemove.setEnabled(true);
            jMenuItemContactListTalk.setEnabled(true);
            jMenuItemContactListAddNew.setEnabled(true);
            jMenuItemContactListRemove.setEnabled(true);
            jDialogLogIn.setVisible(false);
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UserNotFoundException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (InvalidKeyException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UserExistException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
//        try {
//            ChordTools.LogIn(username, password);
//        } catch (NotConnectedException ex) {
//            showMessage(ex.getMessage());
//            return;
//        } catch (UserNotFoundException ex) {
//            showMessage(ex.getMessage());
//            return;
//        } catch (PasswordNotMatchedException ex) {
//            showMessage(ex.getMessage());
//            return;
//        } catch (ServiceException ex) {
//            showMessage(ex.getMessage());
//            return;
//        } catch (UnknownHostException ex) {
//            showMessage(ex.getMessage());
//            return;
//        }
    }//GEN-LAST:event_jButton7ActionPerformed

    private void jMenuItemContactListRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemContactListRemoveActionPerformed
        contacts.remove((String) jList1.getSelectedValue());
        contacts.save();
        refreshContactList();
    }//GEN-LAST:event_jMenuItemContactListRemoveActionPerformed

    private void jMenuItemRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemRemoveActionPerformed
        try {
            openChordWrapper.removeUser(username);
            username = null;
            jMenuItemLogIn.setEnabled(true);
            jMenuItemRegister.setEnabled(true);
            jMenuItemRemove.setEnabled(false);
            jMenuItemLogOut.setEnabled(false);
            jMenuItemContactListAddNew.setEnabled(false);
            jMenuItemContactListRemove.setEnabled(false);
            jMenuItemContactListTalk.setEnabled(true);
        } catch (InvalidKeyException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UserNotFoundException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (BadSignatureException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
    }//GEN-LAST:event_jMenuItemRemoveActionPerformed

    private void jTextField3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField3ActionPerformed
        // TODO add your handling code here:
}//GEN-LAST:event_jTextField3ActionPerformed

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        //         try {
        //            int port = Integer.parseInt(jFormattedTextField2.getText());
        //            if (port > 65535 || port < 1025) {
        //                showMessage("Port must be inetger value between 1025 and 65535!");
        //                return;
        //            }
        //            try {
        //                chord.ChordTools.SetPort(port);
        //            } catch (IOException ex) {
        //                showMessage("I/O error when setting OpenChord port number");
        //            }
        //         } catch (java.lang.NumberFormatException ex) {
        //             showMessage("Port must be inetger value between 1025 and 65535!");
        //         }
        jDialogSettings.setVisible(false);
}//GEN-LAST:event_jButton4ActionPerformed

    private void jMenuItemLogOutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemLogOutActionPerformed
        try {
            openChordWrapper.changeState(username, false);
            username = null;
            contacts.save();
            for(Component c : jTabbedPane1.getComponents()) {
                try {
                    ((TalkPane) c).close();
                    jTabbedPane1.remove(c);
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, ex);
                }
            }
            jMenuItemLogIn.setEnabled(true);
            jMenuItemRegister.setEnabled(true);
            jMenuItemRemove.setEnabled(false);
            jMenuItemLogOut.setEnabled(false);
            jMenuItemContactListAddNew.setEnabled(false);
            jMenuItemContactListRemove.setEnabled(false);
            jMenuItemContactListTalk.setEnabled(true);
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UserNotFoundException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (InvalidKeyException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UserExistException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
    }//GEN-LAST:event_jMenuItemLogOutActionPerformed

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainWindow().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JButton jButton5;
    private javax.swing.JButton jButton6;
    private javax.swing.JButton jButton7;
    private javax.swing.JDialog jDialogConnect;
    private javax.swing.JDialog jDialogLogIn;
    private javax.swing.JDialog jDialogRegistration;
    private javax.swing.JDialog jDialogSettings;
    private javax.swing.JFormattedTextField jFormattedTextField2;
    private javax.swing.JFrame jFrame1;
    private javax.swing.JFrame jFrameSearch;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JList jList1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenu jMenuChord;
    private javax.swing.JMenu jMenuConnect;
    private javax.swing.JMenuItem jMenuItemConncectCreateNew;
    private javax.swing.JMenuItem jMenuItemConnectToExisiting;
    private javax.swing.JMenuItem jMenuItemContactListAddNew;
    private javax.swing.JMenuItem jMenuItemContactListRemove;
    private javax.swing.JMenuItem jMenuItemContactListTalk;
    private javax.swing.JMenuItem jMenuItemDisconnect;
    private javax.swing.JMenuItem jMenuItemLogIn;
    private javax.swing.JMenuItem jMenuItemLogOut;
    private javax.swing.JMenuItem jMenuItemRegister;
    private javax.swing.JMenuItem jMenuItemRemove;
    private javax.swing.JMenu jMenuUser;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPasswordField jPasswordField1;
    private javax.swing.JPasswordField jPasswordField2;
    private javax.swing.JPasswordField jPasswordField3;
    private javax.swing.JPopupMenu jPopupMenuContactList;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    private javax.swing.JTextField jTextField4;
    private javax.swing.JTextField jTextField5;
    // End of variables declaration//GEN-END:variables


    /**
     * 
     * @param socket
     */
    public void createConversation(final Socket socket) {
        try {
            jTabbedPane1.add(
                    new TalkPane(socket, jTabbedPaneLastIndex, username),
                    jTabbedPaneLastIndex++);
        } catch (IOException ex) {
            showMessage(ex.getMessage());
        }
        jFrame1.setVisible(true);
    }

    /**
     * Shows message in dialog window.
     * @param text
     */
    public void showMessage(final String text) {
        JOptionPane.showMessageDialog(null, text);
    }
    
    private void initContactList() {
        contacts = new Contacts();
        refreshContactList();
    }

    private void refreshContactList() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                jList1.setListData(new Vector<String>(contacts.values()));
            }
        });
    }

    private void initConversation(String username) {
        try {
            UserData us = openChordWrapper.getUserData(username);
            if (!us.isOnline()) {
                JOptionPane.showMessageDialog(
                        null, "User with name " + username + " is offline");
                return;
            }
            InetAddress ia = us.getInetAddress();
            createConversation(new Socket(ia, NetSettings.TCP_PORT));
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (ServiceException ex) {
            JOptionPane.showMessageDialog(null, ex);
        } catch (UserNotFoundException ex) {
            JOptionPane.showMessageDialog(null, ex);
        }
    }

    private void initServer() {
        try {
            ServerThread serverThread = new ServerThread();
            serverThread.addObserver(new ServerObserver(this));
            new Thread(serverThread).start();
        } catch (IOException ex) {
            showMessage("Port: " + NetSettings.TCP_PORT + " must be free." );
        }
    }

}
